/**
 * Produto.java
 * Copyright (C) 2009 Jose Mauro da Silva Sandy
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

package negocio.produto;

import java.io.IOException;
import java.util.*;
import persistencia.produto.PProduto;
import utils.*;
/**
 *
 * @author jmsandy
 */
public class Produto {

    // <editor-fold defaultstate="collapsed" desc="FIELDS">
    private String cod_objeto;
    private Integer codProd;
    private String descricao;
    private String idGrupo;
    private String idUnidade1;
    private String idUnidade2;
    private double menorPreco     = 0;
    private double precoUltCompra = 0;
    private double fatorConversao = 1;
    private Date dataUltCompra    = null;
    private Boolean update;
    private Boolean isNew         = true;
    private String errorMessage;
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc="ACESSORES">
    // Atributo cod_objeto
    public String getCod_objeto() {
        return cod_objeto; }
    public void setCod_objeto(String cod_objeto) {
        this.cod_objeto = cod_objeto; }
    // Atributo codProd
    public Integer getCodProd() {
        return codProd; }
    public void setCodProd(Integer codProd) {
        this.codProd = codProd; }
    // Atributo descricao
    public String getDescricao() {
        return descricao; }
    public void setDescricao(String descricao) {
        this.descricao = descricao; }
    // Atributo idGrupo
    public String getIdGrupo() {
        return idGrupo; }
    public void setIdGrupo(String idGrupo) {
        this.idGrupo = idGrupo; }
    // Atributo unidade1
    public String getIdUnidade1() {
        return idUnidade1; }
    public void setIdUnidade1(String idUnidade1) {
        this.idUnidade1 = idUnidade1; }
    // Atributo unidade2
    public String getIdUnidade2() {
        return idUnidade2; }
    public void setIdUnidade2(String idUnidade2) {
        this.idUnidade2 = idUnidade2; }
    // Atributo menorPreco
    public double getMenorPreco() {
        return menorPreco; }
    public void setMenorPreco(double menorPreco) {
        this.menorPreco = menorPreco; }
    // Atributo precoUltCompra
    public double getPrecoUltCompra() {
        return precoUltCompra; }
    public void setPrecoUltCompra(double precoUltCompra) {
        this.precoUltCompra = precoUltCompra; }
    // Atributo fatorConversao
    public double getFatorConversao() {
        return fatorConversao; }
    public void setFatorConversao(double fatorConversao) {
        this.fatorConversao = fatorConversao; }
    // Atributo dataUltCompra
    public Date getDataUltCompra() {
        return dataUltCompra; }
    public void setDataUltCompra(Date dataUltCompra) {
        this.dataUltCompra = dataUltCompra; }
    // Atributo update
    public Boolean getWasUpdated() {
        return update; }
    public void setWasUpdated(Boolean update) {
        this.update = update; }
    // Atributo isNew
    public Boolean getIsNew() {
        return isNew; }
    public void setIsNew(Boolean isNew) {
        this.isNew = isNew; }
    // Atributo errorMessage
    public String getErrorMessage() {
        return errorMessage; }
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc="Constructor">
    public Produto(){
        this.update  = false;
        this.isNew   = true;
    }
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc="METHODS">
    /**
     * Verifica se um objeto e novo
     * @return retorna verdadeiro se o objeto for novo
     */
    public Boolean isNew(){
        return this.isNew;
    }

    /**
     * Realiza a insercao de um objeto na base de dados
     * @return TRUE se o objeto foi persistido e FALSE caso contrario
     */
    public Boolean insert() throws IOException{
        Boolean ret = true;

        // Verifica se um objeto pode ser inserido no banco de dados
        if(validateFields()){
            PProduto pProduto = new PProduto();

            // Verifica se o objeto foi inserido com sucesso
            if(!pProduto.insert(this)){
                ret = false;
                this.errorMessage = ErrorMessage.MSG_GERAL_BANCO + "\n" +
                                    ErrorMessage.MSG_GERAL_LOG;
            }
            else{
                this.update = true;
                this.isNew = false;
            }
        }
        else{
            ret = false;
            this.errorMessage = ErrorMessage.MSG_GERAL_OBRIG;
        }
        return ret;
    }

    /**
     * Realiza a atualizacao de um objeto na base de dados
     * @return TRUE se o objeto foi persistido e FALSE caso contrario
     */
    public Boolean update() throws IOException{
        Boolean ret = true;

        // Verifica se um objeto pode ser inserido no banco de dados
        this.update = true;
        if(validateFields()){
            PProduto pProduto = new PProduto();

            // Verifica se o objeto foi inserido com sucesso
            if(!pProduto.update(this)) {
                ret = false;
                this.errorMessage = ErrorMessage.MSG_GERAL_BANCO + "\n" +
                                    ErrorMessage.MSG_GERAL_LOG;
            }
            else{
                this.update = true;
                this.isNew = false;
            }
        }
        else{
            ret = false;
            this.errorMessage = ErrorMessage.MSG_GERAL_OBRIG;
        }
        return ret;
    }

    /**
     * Realiza a delecao de um objeto na base de dados
     * @return TRUE se o objeto foi persistido e FALSE caso contrario
     */
    public Boolean delete() throws IOException{
        Boolean ret = true;

        // Verifica se um objeto e novo
        if(!this.isNew()){
            PProduto pProduto = new PProduto();

            if(!pProduto.existsItem(this.cod_objeto)){
                // Verifica se o objeto foi deletado com sucesso
                if(!pProduto.delete(this)){
                    ret = false;
                    this.errorMessage = ErrorMessage.MSG_GERAL_BANCO + "\n" +
                                        ErrorMessage.MSG_GERAL_LOG;
                }
            }
            else{
                ret = false;
                errorMessage = ErrorMessage.MSG_PRODUTO_EXCLUSAO;
            }
        }
        else ret = false;

        return ret;
    }

    /**
     * Atualiza as informacoes de compra para uma lista de produtos
     * @param lstProdutos lista de produtos que serao atualizados
     * @return TRUE se atualizado com sucesso e FALSE caso contrario
     */
    public Boolean atualizLista(ArrayList<Produto> lstProdutos) throws IOException{
        return (new PProduto()).atualizLista(lstProdutos);
    }
    
    /**
     * Recupera um produto pelo seu codigo
     * @param codProduto - codigo do produto a ser recuperado
     * @return o produto recuperado
     */
    public Produto refresh(Integer codProduto){
        Produto produto = null;

        try{

            // Verifica se foi informado algum codigo
            if(codProduto > 0){
                // Recupera o produto em questao
                PProduto pProduto = new PProduto();
                produto = new Produto();

                produto = pProduto.refresh(codProduto.toString(),
                                                    PProduto.K_REC_COD_PRODUTO);
                this.errorMessage = pProduto.isError() ?
                                        ErrorMessage.MSG_GERAL_BANCO + "\n" +
                                        ErrorMessage.MSG_GERAL_LOG : "";
            }
        }catch(Exception ex){
            Log.gravarLog(RedirectStackTrace.stackTraceToString(ex), this);
            produto = null;
        }
        return produto;
    }

    /**
     * Recupera um produto pelo seu codigo
     * @param codProduto - codigo do produto a ser recuperado
     * @return o produto recuperado
     */
    public Produto refresh(String codProduto){
        Produto produto = null;

        try{
            // Recupera o produto em questao
            PProduto pProduto = new PProduto();
            produto = new Produto();

            produto = pProduto.refresh(codProduto,PProduto.K_REC_COD_OBJETO);
            this.errorMessage = pProduto.isError() ?
                                    ErrorMessage.MSG_GERAL_BANCO + "\n" +
                                    ErrorMessage.MSG_GERAL_LOG : "";
        }catch(Exception ex){
            Log.gravarLog(RedirectStackTrace.stackTraceToString(ex), this);
            produto = null;
        }
        return produto;
    }

    /**
     * Recupera o ultimo codigo inserido
     */
    public Integer recUltCodigo(){
        Integer lastCod = 0;

        try{
            PProduto pProduto = new PProduto();
            lastCod = pProduto.recUltCodigo();

            this.errorMessage = pProduto.isError() ?
                                    ErrorMessage.MSG_GERAL_BANCO + "\n" +
                                    ErrorMessage.MSG_GERAL_LOG : "";
        }catch(Exception ex){
            Log.gravarLog(RedirectStackTrace.stackTraceToString(ex), this);
            lastCod = 0;
        }
        return lastCod;
    }

    /**
     * Recupera uma lista de produtos que satisfaca aos filtros informados
     * no campo produto
     * @param produto - caracteristicas do produto a ser buscado
     * @return lista de produtos
     */
    public ArrayList<Produto> recLstProdutos(Produto produto){
        // Lista de grupos de retorno
        ArrayList<Produto> lstProdutos = new ArrayList<Produto>();

        try{
            // Recupera a lista de produtos
            PProduto pProduto = new PProduto();

            // Verifica se o id do grupo esta nulo
            if(produto.getIdGrupo() == null) produto.setIdGrupo("");

            lstProdutos = pProduto.recLstProdutos(produto);

            this.errorMessage = pProduto.isError() ?
                                    ErrorMessage.MSG_GERAL_BANCO + "\n" +
                                    ErrorMessage.MSG_GERAL_LOG : "";
        }catch(Exception ex){
            Log.gravarLog(RedirectStackTrace.stackTraceToString(ex), this);
            lstProdutos = null;
        }

        return lstProdutos;
    }

    // Realiza a validacao dos campos para insercao
    private Boolean validateFields(){
        Boolean ret = true;

        // Verifica se o campo esta marcado como atualizado
        if(this.isNew()) this.cod_objeto = GenerateID.gerarID();

        // Verifica se foi informada alguma descricao
        if(this.descricao.isEmpty() || this.descricao.length() > 60) ret = false;
        // Verifica se foi informada algum grupo
        else if(this.idGrupo.isEmpty()) ret = false;
        else{

            // Verifica a existencia das unidades em questao
            Unidade unit = new Unidade();
            unit = 
               (this.idUnidade1.length() <= 1 || this.idUnidade1.length() > 3) ?
                                    null : unit.unitExists(this.idUnidade1);

            if(unit == null) ret = false;
            else{
                this.idUnidade1 = unit.getCod_objeto();

                unit = new Unidade();
                unit =
               (this.idUnidade2.length() <= 1 || this.idUnidade2.length() > 3) ?
                                    null : unit.unitExists(this.idUnidade2);

                if(unit == null) ret = false;
                else this.idUnidade2 = unit.getCod_objeto();
            }
        }

        // Verifica a existencia de um fator de conversao
        if(ret){
            ret = this.fatorConversao != 0 ? true : false;
        }

        return ret;
    }
    //</editor-fold>
}